package com.zebra.common.concurrent;


import io.netty.util.internal.logging.InternalLogger;
import io.netty.util.internal.logging.InternalLoggerFactory;

import java.util.concurrent.ExecutorService;

/**
 * Manager of processors 处理器管理类<br>
 * Maintains the relationship between command and command processor through command code.
 * 
 * @author sk
 * @version $Id: ProcessorManager.java, v 0.1 Sept 6, 2015 2:49:47 PM tao Exp $
 */

public class ZebraExecutorManager {
    private static final InternalLogger logger = InternalLoggerFactory.getInstance(ZebraExecutorManager.class);
    private static ZebraExecutorManager processorManager = new ZebraExecutorManager();

    private ZebraExecutorGroup executorGroup;
    private ZebraScheduler defaultScheduler;

    /** The default executor, if no executor is set for processor, this one will be used 如果没有为处理类设置线程池,则默认此线程池*/
    private ExecutorService                                      defaultExecutor;

    /**
     * minPoolSize(线程池的基本大小): 32
     * maxPoolSize(线程池最大大小): 512
     * queueSize(任务队列大小): 1024
     * keepAliveTime(线程活动保持时间): 60s
     */
    private int                                                  minPoolSize    = ExecutorConfigManager
                                                                                    .default_tp_min_size();

    private int                                                  minSchedulerPoolSize    = ExecutorConfigManager
                                                                                    .default_tsp_min_size();

    private int                                                  maxPoolSize    = ExecutorConfigManager
                                                                                    .default_tp_max_size();

    private int                                                  queueSize      = ExecutorConfigManager
                                                                                    .default_tp_queue_size();

    private long                                                 keepAliveTime  = ExecutorConfigManager
                                                                                    .default_tp_keepalive_time();

    private ZebraExecutorManager() {
        defaultExecutor = ZebraThreadPool.buildThreadPool(minPoolSize,  maxPoolSize, queueSize, keepAliveTime, "zebra-pool");
        defaultScheduler = new ZebraScheduler(minSchedulerPoolSize);
    }

    public static ZebraExecutorManager getInstance(){
        if (processorManager == null) {
            synchronized (ZebraExecutorManager.class) {
                if (processorManager == null) {
                    processorManager = new ZebraExecutorManager();
                }
            }
        }
        return processorManager;
    }


    public void start(int size){
        if (size == 0){
            return;
        }
        int num = Runtime.getRuntime().availableProcessors()  * size;
        num =  num < 64 ? 64 : num;
        logger.info("Initialize executorGroup size {}", num);
        executorGroup = new ZebraExecutorGroup(num, "zebra-dis");
        executorGroup.start();
    }

    public ZebraExecutor getDisruptorByUserId(long userId){
        int index = (int) (userId % executorGroup.size());
        return executorGroup.getByIndex(index);
    }

    public ZebraExecutor getDisruptor(int no){
        return executorGroup.getByBizNo(no);
    }


    public ExecutorService getDefaultExecutor() {
        return defaultExecutor;
    }

    public ZebraScheduler getDefaultScheduler(){
        return defaultScheduler;
    }
}